package cn.maihe.elg.operation.web.order;

import cn.hutool.core.lang.Validator;
import cn.maihe.elg.operation.config.ElgResourceConfig;
import cn.maihe.elg.operation.exception.ErrorCode;
import cn.maihe.elg.operation.exception.SystemRuntimeException;
import cn.maihe.elg.operation.model.enums.AcceptOrderStatus;
import cn.maihe.elg.operation.model.enums.AttachmentFileType;
import cn.maihe.elg.operation.model.enums.GuaranteeTemplateType;
import cn.maihe.elg.operation.model.vo.order.DownloadAttachmentVO;
import cn.maihe.elg.operation.repository.entity.AcceptOrderInfoDO;
import cn.maihe.elg.operation.repository.entity.GuaranteeAttachmentInfoDO;
import cn.maihe.elg.operation.repository.entity.GuaranteeAttachmentInfoDOCondition;
import cn.maihe.elg.operation.service.order.AcceptOrderInfoService;
import cn.maihe.elg.operation.service.order.GuaranteeAttachmentInfoService;
import cn.maihe.elg.operation.supports.system.ElgResourceService;
import cn.maihe.elg.operation.utils.DocFillUtil;
import cn.maihe.elg.operation.utils.ElgLogger;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Map;

/**
 * @Description
 * @Author WJH
 * @Date 2021/05/20
 */
@RestController
@Slf4j
public class AttachmentInfoController {

    @Resource
    private ElgResourceService elgResourceService;
    @Resource
    private ElgResourceConfig elgResourceConfig;
    @Resource
    private GuaranteeAttachmentInfoService guaranteeAttachmentInfoService;
    @Resource
    private AcceptOrderInfoService acceptOrderInfoService;

    @RequestMapping(value = "/api/attachment/upload/ofd", method = RequestMethod.POST)
    @ResponseBody
    @ApiOperation(value = "上传附件,文件不能为空，大小不能超过10M")
    public Map<String, String> uploadAttachment(@RequestParam("type") String type, @RequestParam("acceptOrderNo") String acceptOrderNo, @RequestParam("file") MultipartFile file) {
        if (file.isEmpty()) {
            throw new SystemRuntimeException(ErrorCode.BSMAU004);
        }
        if (file.getSize() > 10 * 1024 * 1024) {
            throw new SystemRuntimeException(ErrorCode.BSMAU005);
        }
        Map<String, String> reMap = Maps.newHashMap();
        reMap.put("fileName", file.getOriginalFilename());

        AttachmentFileType attachmentFileType;
        try {
            attachmentFileType = AttachmentFileType.resolve(Integer.valueOf(type));
        } catch (Exception e) {
            throw new SystemRuntimeException(ErrorCode.ERROR,"type参数非法");
        }
        if (attachmentFileType != AttachmentFileType.TYPE_5 && attachmentFileType != AttachmentFileType.TYPE_9 && attachmentFileType != AttachmentFileType.TYPE_17) {
            throw new SystemRuntimeException(ErrorCode.ERROR, "type参数非法");
        }
        boolean valid = Validator.isGeneral(acceptOrderNo);
        if(!valid){
            throw new SystemRuntimeException(ErrorCode.ERROR,"acceptOrderNo参数非法");
        }
        AcceptOrderInfoDO orderInfo = acceptOrderInfoService.getByAcceptOrderNo(acceptOrderNo);
        if(orderInfo == null){
            throw new SystemRuntimeException(ErrorCode.ERROR,"查无此acceptOrderNo数据");
        }
        if (attachmentFileType != AttachmentFileType.TYPE_17){
            if(orderInfo.getStatus()==null || orderInfo.getStatus()> AcceptOrderStatus.WAIT_PAY.getStatus() ){
                throw new SystemRuntimeException(ErrorCode.ERROR,"当前订单状态下不允许上传相关文件");
            }
        }
        try {
            if (attachmentFileType == AttachmentFileType.TYPE_17) {
                String fileNamePrefix = "indemnify-" + acceptOrderNo;
                log.info("准备为订单 {} 上传新的理赔凭证，将清理所有以 '{}' 开头的旧文件。", acceptOrderNo, fileNamePrefix);
                elgResourceService.deleteFilesByPrefix(elgResourceConfig.getOfdPath(), acceptOrderNo, fileNamePrefix);
                String fileType = elgResourceService.getFileType(file.getOriginalFilename());
                String uniqueFileName = "indemnify-" + acceptOrderNo + "." + fileType;
                String dbRelativePath = elgResourceService.relativePath(file, elgResourceConfig.getOfdPath(), acceptOrderNo, uniqueFileName);
                String downloadableUrl = elgResourceService.ofdDownloadUrl(dbRelativePath);
                reMap.put("url", downloadableUrl);
            } else {
                String dbRelativePath = elgResourceService.transferAndSaveFile(file, elgResourceConfig.getOfdPath(), acceptOrderNo, attachmentFileType.getDesc());
                reMap.put("url", dbRelativePath);
            }
        } catch (Exception e) {
            ElgLogger.error(log, log -> log.error("上传[{}]附件异常：{}", file.getOriginalFilename(), e.getMessage(), e));
            throw new SystemRuntimeException(ErrorCode.BSMAU007);
        }
        return reMap;
    }


    @PostMapping("/api/attachment/download/ofd")
    public void downloadAttachment(HttpServletResponse response, @RequestBody DownloadAttachmentVO vo) {
        try (OutputStream writer = response.getOutputStream()) {
            Path path;
            if (StringUtils.isNotBlank(vo.getRelativeURI())) {
                path = elgResourceService.getFileByRelativePath(vo.getRelativeURI()).toPath();
            } else if (StringUtils.isNoneBlank(vo.getAcceptOrderNo(), vo.getAttachmentFileType())) {
                GuaranteeAttachmentInfoDO attachmentInfoDO = guaranteeAttachmentInfoService.selectOne(GuaranteeAttachmentInfoDOCondition.builder().andAcceptOrderNoEq(vo.getAcceptOrderNo()).andTypeEq(Integer.valueOf(vo.getAttachmentFileType())).build());
                if (attachmentInfoDO == null) {
                    throw new SystemRuntimeException(ErrorCode.ERROR, "查无此文件");
                }
                path = elgResourceService.getFileByRelativePath(attachmentInfoDO.getFilePath()).toPath();
            } else {
                throw new SystemRuntimeException(ErrorCode.ERROR, "下载文件请求参数不能为空");
            }
            String fileName = elgResourceService.getFileName(path);
            response.setHeader("Content-type", MediaType.APPLICATION_OCTET_STREAM_VALUE);
            response.setCharacterEncoding("UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes("UTF-8"), "ISO-8859-1"));
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
            writer.write(Files.readAllBytes(path));
            writer.close();
            writer.flush();
        } catch (Exception e) {
            log.error("下载附件异常：{}", e.getMessage(), e);
            throw new SystemRuntimeException(ErrorCode.ERROR, "下载附件失败:" + e.getMessage());
        }
    }

    /**
     * 公网下载保函附件地址
     *
     * @param response
     * @param relativeURI
     */
    @GetMapping(value = ElgResourceService.noAuthDownloadPath)
    public void downloadAttachmentNoAuth(HttpServletResponse response, @RequestParam(value = "relativeURI") String relativeURI) {
        try (OutputStream writer = response.getOutputStream()) {
            Path path = null;
            String encodeRelativeURI = relativeURI;
            //特殊的relativeURI处理：即由elgResourceService.fmtSpIdRelativeUri生成的
            path = elgResourceService.getPathByEncodeRelativeURI(encodeRelativeURI);

            String fileName = elgResourceService.getFileNameAndType(path);
            response.setHeader("Content-type", MediaType.APPLICATION_OCTET_STREAM_VALUE);
            // 解决导出文件名中文乱码
            response.setCharacterEncoding("UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes("UTF-8"), "ISO-8859-1"));
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");

            writer.write(Files.readAllBytes(path));
            writer.close();
            writer.flush();
        } catch (Exception e) {
            log.error("下载附件异常：{}", e.getMessage(), e);
            throw new SystemRuntimeException(ErrorCode.ERROR, "下载附件失败:" + e.getMessage());
        }

    }


    @GetMapping(value = "/api/attachment/download/img")
    public void downloadImg(HttpServletResponse response, DownloadAttachmentVO vo) {
        System.out.println("JSON.toJSONString(vo) = " + JSON.toJSONString(vo));
        try (OutputStream writer = response.getOutputStream()) {
            Path path = null;
            if (StringUtils.isNotBlank(vo.getTemplateId())) {
                //临时生成保函模板预览
                GuaranteeTemplateType templateType = GuaranteeTemplateType.resolve(Long.valueOf(vo.getTemplateId()));
                String templateFileName = templateType.getTemplateFileName();
                Path templatePath = elgResourceService.getFileByRelativePath("template/" + templateFileName).toPath();
                String fileName = elgResourceService.getFileName(templateFileName);
                Path targetPdf = elgResourceService.buildSaveAbsolutePath("template", "preview", fileName, "pdf");
                DocFillUtil.doc2pdf(templatePath, targetPdf, null);
                path = targetPdf;
            } else if (StringUtils.isNotBlank(vo.getRelativeURI())) {
                path = elgResourceService.getFileByRelativePath(vo.getRelativeURI()).toPath();
            } else if (StringUtils.isNoneBlank(vo.getAcceptOrderNo(), vo.getAttachmentFileType())) {
                GuaranteeAttachmentInfoDO attachmentInfoDO = guaranteeAttachmentInfoService.selectOne(GuaranteeAttachmentInfoDOCondition.builder().andAcceptOrderNoEq(vo.getAcceptOrderNo()).andTypeEq(Integer.valueOf(vo.getAttachmentFileType())).build());
                if (attachmentInfoDO == null) {
                    throw new SystemRuntimeException(ErrorCode.ERROR, "查无此文件");
                }
                path = elgResourceService.getFileByRelativePath(attachmentInfoDO.getFilePath()).toPath();
            } else {
                throw new SystemRuntimeException(ErrorCode.ERROR, "下载文件请求参数不能为空");
            }

            writer.write(Files.readAllBytes(path));
            writer.flush();
        } catch (Exception e) {
            e.printStackTrace();
        }


    }

    @GetMapping("/api/attachment/download/getOFD")
    public void downloadOFD(HttpServletResponse response,
                            @RequestParam("relativeURI") String relativeURI,
                            @RequestParam(value = "disposition", required = false, defaultValue = "attachment") String disposition) { // <-- 1. 新增参数
        if (StringUtils.isBlank(relativeURI)) {
            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            log.warn("下载文件请求失败：relativeURI 参数为空。");
            return;
        }
        try {
            String decodedRelativeURI = URLDecoder.decode(relativeURI, StandardCharsets.UTF_8.name());
            log.info("开始处理文件请求，解码后的相对路径为: {}, 请求类型: {}", decodedRelativeURI, disposition);
            Path filePath = elgResourceService.getFileByRelativePath(decodedRelativeURI).toPath();
            if (!Files.exists(filePath) || !Files.isReadable(filePath)) {
                log.error("文件未找到或不可读: {}", filePath);
                response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                return;
            }
            String fileName = filePath.getFileName().toString();
            String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name()).replaceAll("\\+", "%20");

            if ("inline".equalsIgnoreCase(disposition)) {
                String mimeType = Files.probeContentType(filePath);
                if (mimeType == null) {
                    if (fileName.toLowerCase().endsWith(".pdf")) {
                        mimeType = "application/pdf";
                    } else {
                        mimeType = MediaType.APPLICATION_OCTET_STREAM_VALUE;
                    }
                }
                response.setContentType(mimeType);
                response.setHeader("Content-Disposition", "inline; filename*=UTF-8''" + encodedFileName);
            } else {
                response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
                response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + encodedFileName);
            }
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
            response.setContentLengthLong(Files.size(filePath));
            try (OutputStream outputStream = response.getOutputStream()) {
                Files.copy(filePath, outputStream);
                outputStream.flush();
            }
            log.info("文件处理成功: {}, 类型: {}", fileName, disposition);

        } catch (Exception e) {
            log.error("处理文件时发生异常：relativeURI={}, 错误信息:{}", relativeURI, e.getMessage(), e);
            if (!response.isCommitted()) {
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            }
        }
    }
}
